package com.rockcent.mall.controller;

import com.rockcent.common.common.JsonResult;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.common.RestDoing;
import com.rockcent.common.controller.BaseController;
import com.rockcent.common.utils.DateUtils;
import com.rockcent.common.utils.RDateUtils;
import com.rockcent.helper.SysMessageHelper;
import com.rockcent.mall.Routes;
import com.rockcent.mall.lib.constants.SysMessageConstants;
import com.rockcent.mall.lib.domain.*;
import com.rockcent.mall.lib.domain.enumclass.*;
import com.rockcent.mall.lib.dto.CustomerWithdrawDto;
import com.rockcent.mall.lib.dto.MerchantWithdrawDto;
import com.rockcent.mall.lib.dto.UserInfoDto;
import com.rockcent.mall.lib.helper.BaseMerchantFundFlowHelper;
import com.rockcent.mall.lib.helper.BaseUserHelper;
import com.rockcent.mall.lib.helper.CustomerFundFlowHelper;
import com.rockcent.mall.lib.repository.*;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Date;

/**
 * Created by DK on 16/12/13.
 * 平台提现审核
 */
@RestController
public class MallWithdrawAuditController extends BaseController{

    private final Logger log = LoggerFactory.getLogger(MallWithdrawAuditController.class);

    @Autowired
    private BaseUserHelper userHelper;

    @Autowired
    private MerchantWithdrawRepository merchantWithdrawRepository;

    @Autowired
    private CustomerWithdrawRepository customerWithdrawRepository;

    @Autowired
    private WithdrawEventRepository withdrawEventRepository;

    @Autowired
    private MerchantFundRepository merchantFundRepository;

    @Autowired
    private CustomerFundRepository customerFundRepository;

    @Autowired
    private BaseMerchantFundFlowHelper baseMerchantFundFlowHelper;

    @Autowired
    private MerchantFundFlowRepository merchantFundFlowRepository;

    @Autowired
    private CustomerFundFlowRepository customerFundFlowRepository;



    /**
     * @api {get} /mall/merchant/apply/withdraw/page 平台 商家提现分页
     * @apiGroup MALL_WITHDRAW_AUDIT
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {String} beginDate 开始时间
     * @apiParam {String} endDate 结束时间
     * @apiParam {String} minAmount 最小金额
     * @apiParam {String} maxAmount 最大金额
     * @apiParam {String} merchantName 商家名称
     * @apiParam {long} merchantId 商家ID
     * @apiParam {String=WAIT_AUDIT("审核中"), PASS("处理中"), FINISHED("已完成"), FAIL("提现失败"), SUCCESS("提现成功")} status <code>必传参数</code>状态 默认WAIT_AUDIT
     *
     * @apiSuccess {date} dateCreated 提现时间
     * @apiSuccess {String} merchantName 商家名称
     * @apiSuccess {String=ALL("全部"), WAIT_AUDIT("审核中"), PASS("处理中"), FAIL("提现失败"), TRANSFER_FAIL("提现失败"), SUCCESS("提现成功")} status 状态
     * @apiSuccess {BigDecimal} amount 提现金额
     * @apiSuccess {String} bankInfo 提现帐号信息
     * @apiSuccess {String} remark 审核备注
     * @apiSuccess {long} merchantId 商家ID
     *
     * @apiSuccessExample { json } Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  "data" : {
     *           "dateCreated": "2016-11-08 15:39:10",
     *           "merchantName": "历史",
     *           "status": "WAIT_AUDIT",
     *           "amount": "23423",
     *           "merchantId": 234,
     *           "bankInfo": "招商+2354283957+二蛋",
     *           "remark": "同意提现"
     *      },
     *      ............
     *  }
     */
    @RequestMapping(value = Routes.MALL_MERCHANT_APPLY_WITHDRAW_PAGE, method = RequestMethod.GET)
    public JsonResult merchantApplyWithdrawPage (HttpServletRequest request, MerchantWithdrawDto dto) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            String beginDate = dto.getBeginDate();
            String endDate = dto.getEndDate();
            if (StringUtils.isNotBlank(beginDate) && StringUtils.isNotBlank(endDate)) {
                if (RDateUtils.parseDate(beginDate, "yyyy-MM-dd").getTime() > RDateUtils.parseDate(endDate, "yyyy-MM-dd").getTime()) {
                    jsonResult.remind("开始时间不能大于结束时间",log);
                    return;
                }
            }
            BigDecimal maxAmount = dto.getMaxAmount();
            BigDecimal minAmount = dto.getMinAmount();
            if (maxAmount != null && minAmount != null) {
                if (minAmount.compareTo(maxAmount) > 0) {
                    jsonResult.remind("最小金额不能大于最大金额",log);
                    return;
                }
            }
            String status = dto.getStatus();
            if (StringUtils.isBlank(status) || !EnumUtils.isValidEnum(WithdrawStatus.class, status)) {
                jsonResult.remind("审核状态只允许 WAIT_AUDIT(\"审核中\"), PASS(\"处理中\"), FINISHED(\"已完成\")",log);
                return;
            }
            Long merchantId = dto.getMerchantId();
            String merchantName = dto.getMerchantName();
            Long anUserInfoDtomallId = userInfoDto.mall.getId();
            PageResult page = this.getPage(dto.getPageNo(), dto.getPageSize());
            PageResult<MerchantWithdrawDto> pageResult = merchantWithdrawRepository.findMallMerchantApplyWithdrawPage(merchantId, merchantName, anUserInfoDtomallId, beginDate, endDate, maxAmount, minAmount, status, page);
            pageResult.setUrl(Routes.MALL_MERCHANT_APPLY_WITHDRAW_PAGE);
            jsonResult.data = pageResult;
        };
        return doing.go(request, log);
    }

    /**
     * @api {put} /mall/audit/merchant/apply/withdraw 审核商家提现
     * @apiGroup MALL_WITHDRAW_AUDIT
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {long} id 提现ID
     * @apiParam {String=FAIL("审核不通过"), PASS("审核通过")} status 审核状态
     * @apiParam {String} remark 审核意见
     *
     * @apiSuccessExample { json } Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  }
     */
    @Transactional
    @RequestMapping(value = Routes.MALL_AUDIT_MERCHANT_APPLY_WITHDRAW, method = RequestMethod.PUT)
    public JsonResult auditMerchantApplyWithdraw (HttpServletRequest request, @RequestBody MerchantWithdrawDto dto) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getId() == null) {
                jsonResult.remind(MerchantWithdraw.CHECK_ID_IS_NOT_NULL,log);;
                return;
            }
            String status = dto.getStatus();
            if (StringUtils.isBlank(status) || !EnumUtils.isValidEnum(WithdrawStatus.class, status)) {
                jsonResult.remind("审核状态只允许 FAIL(\"审核不通过\"), PASS(\"审核通过\")",log);
                return;
            }

            Long anUserInfoDtomallId = userInfoDto.mall.getId();
            MerchantWithdraw merchantWithdraw = merchantWithdrawRepository.findByIdAndMallId(dto.getId(), anUserInfoDtomallId);
            if (merchantWithdraw == null) {
                jsonResult.remind(MerchantWithdraw.REMIND_RECORD_IS_NOT_EXIST,log);;
                return;
            }

            MerchantFund merchantFund = merchantFundRepository.findByMallIdAndMerchantId(anUserInfoDtomallId, merchantWithdraw.getMerchantId());
            if (merchantFund == null) {
                jsonResult.remind("商家帐号异常,请联系客服人员",log);
                return;
            }
            merchantFund=merchantFundRepository.findOne(merchantFund.getId());
            WithdrawEvent withdrawEvent = new WithdrawEvent();
            withdrawEvent.setMallId(anUserInfoDtomallId);
            withdrawEvent.setApplyWithdrawId(dto.getId());
            withdrawEvent.setOperatorId(anUserInfoDtomallId);
            withdrawEvent.setWithdrawCrowd(WithdrawCrowd.MERCHANT);
            String remark = dto.getRemark();

            merchantWithdraw.setRemark(remark);

            // 审核通过
            if (WithdrawStatus.PASS == WithdrawStatus.valueOf(status)) {
                //提现审核通过
                merchantWithdraw.setStatus(WithdrawStatus.PASS);
                merchantWithdrawRepository.save(merchantWithdraw);

                // 审核申请记录
                withdrawEvent.setStatus(WithdrawStatus.PASS);
                withdrawEventRepository.save(withdrawEvent);
            }
            // 审核不通过
            if (WithdrawStatus.FAIL == WithdrawStatus.valueOf(status)) {

                if (StringUtils.isBlank(remark)) {
                    jsonResult.remind("审核意见 不能为空",log);
                    return;
                }

                //商家账户可用资金增加, 冻结资金减少
                merchantFund.setAvailableAmount(merchantFund.getAvailableAmount().add(merchantWithdraw.getAmount()));
                merchantFund.setFrozen(merchantFund.getFrozen().subtract(merchantWithdraw.getAmount()));
                merchantFundRepository.save(merchantFund);

                //提现失败
                merchantWithdraw.setStatus(WithdrawStatus.FAIL);
                merchantWithdrawRepository.save(merchantWithdraw);

                // 审核申请记录
                withdrawEvent.setStatus(WithdrawStatus.FAIL);
                withdrawEventRepository.save(withdrawEvent);
                String content = SysMessageConstants.M2B_MERCHANT_APPLY_WITHDRAW_UNPASS.getContent();
                content = MessageFormat.format(content, DateUtils.formatDate(merchantWithdraw.getDateCreated()), remark);
                SysMessage message= SysMessageHelper.SINGLETON.createMsgBean(SysMessageConstants.M2B_MERCHANT_APPLY_WITHDRAW_UNPASS, SysMessageType.SYS, content);


                Long merchantId = merchantFund.getMerchantId();
                SysMessageHelper.SINGLETON.pushMsgByMallAndMerchantId(message, null, merchantId);


            }

        };
        return doing.go(request, log);
    }

    /**
     * @api {put} /mall/confirm/merchant/apply/withdraw 确认商家提现
     * @apiGroup MALL_WITHDRAW_AUDIT
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {long} id 提现ID
     * @apiParam {String=TRANSFER_FAIL("转账失败"), SUCCESS("转账成功")} status <code>必传参数</code> 状态
     * @apiParam {String} certificateUrl 转账凭证URL (status值为SUCCESS时,才传值, 为TRANSFER_FAIL时, 为空)
     * @apiParam {String} remark 审核意见 (status值为SUCCESS时, 为空, 为TRANSFER_FAIL时,才传值)
     *
     * @apiSuccessExample { json } Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  }
     */
    @Transactional
    @RequestMapping(value = Routes.MALL_CONFIRM_MERCHANT_APPLY_WITHDRAW, method = RequestMethod.PUT)
    public JsonResult confirmMerchantApplyWithdraw (HttpServletRequest request, @RequestBody MerchantWithdrawDto dto) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getId() == null) {
                jsonResult.remind(MerchantWithdraw.CHECK_ID_IS_NOT_NULL,log);;
                return;
            }

            if (StringUtils.isBlank(dto.getStatus()) || !EnumUtils.isValidEnum(WithdrawStatus.class, dto.getStatus())) {
                jsonResult.remind("审核状态只允许 TRANSFER_FAIL(\"审核不通过\"), SUCCESS(\"提现成功\")",log);
                return;
            }

            MerchantWithdraw merchantWithdraw = merchantWithdrawRepository.findByIdAndMallId(dto.getId(), userInfoDto.mall.getId());
            if (merchantWithdraw == null) {
                jsonResult.remind(MerchantWithdraw.REMIND_RECORD_IS_NOT_EXIST,log);;
                return;
            }

            MerchantFund merchantFund = merchantFundRepository.findByMallIdAndMerchantId(userInfoDto.mall.getId(), merchantWithdraw.getMerchantId());
            if (merchantFund == null) {
                jsonResult.remind("商家帐号异常,请联系客服人员",log);
                return;
            }

            WithdrawEvent withdrawEvent = new WithdrawEvent();
            withdrawEvent.setMallId(userInfoDto.mall.getId());
            withdrawEvent.setApplyWithdrawId(dto.getId());
            withdrawEvent.setOperatorId(userInfoDto.mall.getId());
            withdrawEvent.setWithdrawCrowd(WithdrawCrowd.MERCHANT);


            SysMessage message = null;

            // 转账失败
            BigDecimal amount = merchantWithdraw.getAmount();
            if (WithdrawStatus.TRANSFER_FAIL == WithdrawStatus.valueOf(dto.getStatus())) {

                String remark = dto.getRemark();
                if (StringUtils.isBlank(dto.getRemark())) {
                    jsonResult.remind("转账失败时, 失败备注 不能为空",log);
                    return;
                }
                merchantWithdraw.setRemark(dto.getRemark());

                // 审核申请记录
                merchantWithdraw.setStatus(WithdrawStatus.TRANSFER_FAIL);
                withdrawEventRepository.save(withdrawEvent);

                //商家账户可用资金增加, 冻结资金减少
                merchantFund.setAvailableAmount(merchantFund.getAvailableAmount().add(amount));
                merchantFund.setFrozen(merchantFund.getFrozen().subtract(amount));
                merchantFundRepository.save(merchantFund);

                //提现失败
                merchantWithdraw.setStatus(WithdrawStatus.TRANSFER_FAIL);
                merchantWithdrawRepository.save(merchantWithdraw);


                Date dateCreated = merchantWithdraw.getDateCreated();
                String content = SysMessageConstants.M2B_CONFIRM_MERCHANT_APPLY_WITHDRAW__UNPASS.getContent();
                content = MessageFormat.format(content, DateUtils.formatDate(dateCreated), remark);
                message = SysMessageHelper.SINGLETON.createMsgBean(SysMessageConstants.M2B_CONFIRM_MERCHANT_APPLY_WITHDRAW__UNPASS, SysMessageType.FINANCE, content);


            }

            //转账成功
            else if (WithdrawStatus.SUCCESS == WithdrawStatus.valueOf(dto.getStatus())) {

                if (StringUtils.isBlank(dto.getCertificateUrl())) {
                    jsonResult.remind("转账成功时, 转账凭证URL 不能为空",log);
                    return;
                }
                merchantWithdraw.setCertificateUrl(dto.getCertificateUrl());

                // 交易流水
                MerchantOrder merchantOrder = new MerchantOrder();
                String orderNum = String.format("%s%d%d", String.format("%03d", userInfoDto.mall.getId()), 4L, new Date().getTime()); // 生产订单号 4L代表提现类型
                merchantOrder.setMallId(userInfoDto.mall.getId());
                merchantOrder.setMerchantId(merchantWithdraw.getMerchantId());
                merchantOrder.setOrderNum(orderNum);
                MerchantFundFlow merchantFundFlow = baseMerchantFundFlowHelper.create(merchantFund, merchantOrder, amount, BigDecimal.ZERO, amount, null, FundTransactionFlow.EXPEND, MerchantFundFlowTransactionType.A_APPLY_WITHDRAW_EXPEND);
                merchantFundFlowRepository.save(merchantFundFlow);

                //商家冻结资金减少,总金额减少
                merchantFund.setTotalAmount(merchantFund.getTotalAmount().subtract(amount));
                merchantFund.setFrozen(merchantFund.getFrozen().subtract(amount));
                merchantFundRepository.save(merchantFund);

                //提现审核通过
                merchantWithdraw.setStatus(WithdrawStatus.SUCCESS);
                merchantWithdraw.setTransactionId(merchantFundFlow.getMerchantOrderNum());
                merchantWithdraw.setCertificateUrl(dto.getCertificateUrl());
                merchantWithdrawRepository.save(merchantWithdraw);

                // 提现成功记录
                withdrawEvent.setStatus(WithdrawStatus.SUCCESS);
                withdrawEventRepository.save(withdrawEvent);

                String content = SysMessageConstants.M2B_CONFIRM_MERCHANT_APPLY_WITHDRAW_PASS.getContent();
                Date dateCreated = merchantWithdraw.getDateCreated();
                content = MessageFormat.format(content, DateUtils.formatDate(dateCreated));
                message = SysMessageHelper.SINGLETON.createMsgBean(SysMessageConstants.M2B_CONFIRM_MERCHANT_APPLY_WITHDRAW_PASS, SysMessageType.FINANCE,content);


            }

            //广播消息
            Long merchantId = merchantWithdraw.getMerchantId();
            SysMessageHelper.SINGLETON.pushMsgByMallAndMerchantId(message, null, merchantId);


        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /mall/merchant/withdraw/info 平台 商家提现详情
     * @apiGroup MALL_WITHDRAW_AUDIT
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {long} id 提现ID
     *
     * @apiSuccess {String} certificateUrl 提现帐号信息 (提现成功,显示该字段值)
     * @apiSuccess {String} remark 备注 (提现失败,显示该字段值)
     *
     * @apiSuccessExample { json } Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  "data" : {
     *           "certificateUrl": "843523450987234.jpg",
     *           "remark": "招商+2354283957+二蛋"
     *      }
     *  }
     */
    @RequestMapping(value = Routes.MALL_MERCHANT_WITHDRAW_INFO, method = RequestMethod.GET)
    public JsonResult merchantWithdrawInfo (HttpServletRequest request, MerchantWithdrawDto dto) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getId() == null) {
                jsonResult.remind(MerchantWithdraw.CHECK_ID_IS_NOT_NULL,log);;
                return;
            }
            MerchantWithdraw merchantWithdraw = merchantWithdrawRepository.findByIdAndMallId(dto.getId(), userInfoDto.mall.getId());
            jsonResult.data = merchantWithdraw;
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /mall/customer/apply/withdraw/page 平台 买家提现分页
     * @apiGroup MALL_WITHDRAW_AUDIT
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {String} beginDate 开始时间
     * @apiParam {String} endDate 结束时间
     * @apiParam {String} minAmount 最小金额
     * @apiParam {String} maxAmount 最大金额
     * @apiParam {long} customerId 买家ID
     * @apiParam {String=WAIT_AUDIT("审核中"), PASS("处理中"), FINISHED("已完成")} status <code>必传参数</code>状态 默认WAIT_AUDIT
     *
     * @apiSuccess {date} dateCreated 提现时间
     * @apiSuccess {String=ALL("全部"), WAIT_AUDIT("审核中"), PASS("处理中"), TRANSFER_FAIL("提现失败"), FAIL("提现失败"), SUCCESS("提现成功")} status 状态
     * @apiSuccess {BigDecimal} amount 提现金额
     * @apiSuccess {String} bankInfo 提现帐号信息
     * @apiSuccess {long} customerId 买家ID
     * @apiSuccess {String} customerName 买家名称
     * @apiSuccess {String} transactionId 流水号
     *
     * @apiSuccessExample { json } Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  "data" : {
     *           "dateCreated": "2016-11-08 15:39:10",
     *           "status": "WAIT_AUDIT",
     *           "amount": "23423",
     *           "customerId": 234,
     *           "customerName": "二蛋",
     *           "transactionId": "23423423424",
     *           "bankInfo": "招商+2354283957+二蛋"
     *      },
     *      ............
     *  }
     */
    @RequestMapping(value = Routes.MALL_CUSTOMER_APPLY_WITHDRAW_PAGE, method = RequestMethod.GET)
    public JsonResult customerApplyWithdrawPage (HttpServletRequest request, CustomerWithdrawDto dto) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (StringUtils.isNotBlank(dto.getBeginDate()) && StringUtils.isNotBlank(dto.getEndDate())) {
                if (RDateUtils.parseDate(dto.getBeginDate(), "yyyy-MM-dd").getTime() > RDateUtils.parseDate(dto.getEndDate(), "yyyy-MM-dd").getTime()) {
                    jsonResult.remind("开始时间不能大于结束时间",log);
                    return;
                }
            }
            if (dto.getMaxAmount() != null && dto.getMinAmount() != null) {
                if (dto.getMinAmount().compareTo(dto.getMaxAmount()) > 0) {
                    jsonResult.remind("最小金额不能大于最大金额",log);
                    return;
                }
            }
            if (StringUtils.isBlank(dto.getStatus()) || !EnumUtils.isValidEnum(WithdrawStatus.class, dto.getStatus())) {
                jsonResult.remind("审核状态只允许 WAIT_AUDIT(\"审核中\"), PASS(\"处理中\"), FINISHED(\"已完成\")",log);
                return;
            }
            PageResult<CustomerWithdrawDto> pageResult = customerWithdrawRepository.findMallCustomerApplyWithdrawPage(dto.getCustomerId(), userInfoDto.mall.getId(), dto.getBeginDate(), dto.getEndDate(), dto.getMaxAmount(), dto.getMinAmount(), dto.getStatus(), this.getPage(dto.getPageNo(), dto.getPageSize()));
            pageResult.setUrl(Routes.MALL_CUSTOMER_APPLY_WITHDRAW_PAGE);
            jsonResult.data = pageResult;
        };
        return doing.go(request, log);
    }

    /**
     * @api {put} /mall/audit/customer/apply/withdraw 审核买家提现
     * @apiGroup MALL_WITHDRAW_AUDIT
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {long} id 提现ID
     * @apiParam {String=FAIL("审核不通过"), PASS("审核通过")} status 审核状态
     * @apiParam {String} remark 审核意见
     *
     * @apiSuccessExample { json } Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  }
     */
    @Transactional
    @RequestMapping(value = Routes.MALL_AUDIT_CUSTOMER_APPLY_WITHDRAW, method = RequestMethod.PUT)
    public JsonResult auditCustomerApplyWithdraw (HttpServletRequest request, @RequestBody CustomerWithdrawDto dto) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getId() == null) {
                jsonResult.remind(MerchantWithdraw.CHECK_ID_IS_NOT_NULL,log);;
                return;
            }
            if (StringUtils.isBlank(dto.getStatus()) || !EnumUtils.isValidEnum(WithdrawStatus.class, dto.getStatus())) {
                jsonResult.remind("审核状态只允许 FAIL(\"审核不通过\"), PASS(\"审核通过\")",log);
                return;
            }
            if (StringUtils.isBlank(dto.getRemark())) {
                jsonResult.remind("审核意见 不能为空",log);
                return;
            }
            CustomerWithdraw customerWithdraw = customerWithdrawRepository.findByIdAndMallId(dto.getId(), userInfoDto.mall.getId());
            if (customerWithdraw == null) {
                jsonResult.remind(MerchantWithdraw.REMIND_RECORD_IS_NOT_EXIST,log);;
                return;
            }
            CustomerFund customerFund = customerFundRepository.findByCustomerId(customerWithdraw.getCustomerId());
            if (customerFund == null) {
                jsonResult.remind("买家帐号异常,请联系客服人员",log);
                return;
            }

            WithdrawEvent withdrawEvent = new WithdrawEvent();
            withdrawEvent.setMallId(userInfoDto.mall.getId());
            withdrawEvent.setApplyWithdrawId(dto.getId());
            withdrawEvent.setOperatorId(userInfoDto.mall.getId());
            withdrawEvent.setWithdrawCrowd(WithdrawCrowd.MERCHANT);

            customerWithdraw.setRemark(dto.getRemark());

            // 审核通过
            if (WithdrawStatus.PASS == WithdrawStatus.valueOf(dto.getStatus())) {

                withdrawEvent.setStatus(WithdrawStatus.PASS);
                customerWithdraw.setStatus(WithdrawStatus.PASS);

                //提现审核通过
                customerWithdrawRepository.save(customerWithdraw);

                // 审核申请记录
                withdrawEventRepository.save(withdrawEvent);
            }
            // 审核不通过
            if (WithdrawStatus.FAIL == WithdrawStatus.valueOf(dto.getStatus())) {

                //提现失败
                customerWithdraw.setStatus(WithdrawStatus.FAIL);
                customerWithdrawRepository.save(customerWithdraw);

                //商家账户可用资金增加, 冻结资金减少
                customerFund.setAvailableAmount(customerFund.getAvailableAmount().add(customerWithdraw.getAmount()));
                customerFund.setFrozen(customerFund.getFrozen().subtract(customerWithdraw.getAmount()));
                customerFundRepository.save(customerFund);

                // 审核申请记录
                withdrawEvent.setStatus(WithdrawStatus.FAIL);
                withdrawEventRepository.save(withdrawEvent);
            }

        };
        return doing.go(request, log);
    }

    /**
     * @api {put} /mall/confirm/customer/apply/withdraw 确认买家提现
     * @apiGroup MALL_WITHDRAW_AUDIT
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {long} id 提现ID
     * @apiParam {String=TRANSFER_FAIL("转账失败"), SUCCESS("转账成功")} status <code>必传参数</code> 状态
     * @apiParam {String} certificateUrl 转账凭证URL (status值为SUCCESS时,才传值, 为TRANSFER_FAIL时, 为空)
     * @apiParam {String} remark 审核意见 (status值为SUCCESS时, 为空, 为TRANSFER_FAIL时,才传值)
     *
     * @apiSuccessExample { json } Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  }
     */
    @Transactional
    @RequestMapping(value = Routes.MALL_CONFIRM_CUSTOMER_APPLY_WITHDRAW, method = RequestMethod.PUT)
    public JsonResult confirmCustomerApplyWithdraw (HttpServletRequest request, @RequestBody CustomerWithdrawDto dto) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getId() == null) {
                jsonResult.remind(MerchantWithdraw.CHECK_ID_IS_NOT_NULL,log);;
                return;
            }

            if (StringUtils.isBlank(dto.getStatus()) || !EnumUtils.isValidEnum(WithdrawStatus.class, dto.getStatus())) {
                jsonResult.remind("审核状态只允许 TRANSFER_FAIL(\"审核不通过\"), SUCCESS(\"提现成功\")",log);
                return;
            }
            CustomerWithdraw customerWithdraw = customerWithdrawRepository.findByIdAndMallId(dto.getId(), userInfoDto.mall.getId());
            if (customerWithdraw == null) {
                jsonResult.remind(MerchantWithdraw.REMIND_RECORD_IS_NOT_EXIST,log);;
                return;
            }
            CustomerFund customerFund = customerFundRepository.findByCustomerId(customerWithdraw.getCustomerId());
            if (customerFund == null) {
                jsonResult.remind("买家帐号异常,请联系客服人员",log);
                return;
            }

            WithdrawEvent withdrawEvent = new WithdrawEvent();
            withdrawEvent.setMallId(userInfoDto.mall.getId());
            withdrawEvent.setApplyWithdrawId(dto.getId());
            withdrawEvent.setOperatorId(userInfoDto.mall.getId());
            withdrawEvent.setWithdrawCrowd(WithdrawCrowd.MERCHANT);

            // 转账失败
            if (WithdrawStatus.TRANSFER_FAIL == WithdrawStatus.valueOf(dto.getStatus())) {

                if (StringUtils.isBlank(dto.getRemark())) {
                    jsonResult.remind("转账失败时, 失败备注 不能为空",log);
                    return;
                }
                customerWithdraw.setRemark(dto.getRemark());
                // 审核申请记录
                customerWithdraw.setStatus(WithdrawStatus.TRANSFER_FAIL);
                withdrawEventRepository.save(withdrawEvent);

                //提现失败
                customerWithdraw.setStatus(WithdrawStatus.TRANSFER_FAIL);
                customerWithdrawRepository.save(customerWithdraw);

                //商家账户可用资金增加, 冻结资金减少
                customerFund.setAvailableAmount(customerFund.getAvailableAmount().add(customerWithdraw.getAmount()));
                customerFund.setFrozen(customerFund.getFrozen().subtract(customerWithdraw.getAmount()));
                customerFundRepository.save(customerFund);
            }

            //转账成功
            if (WithdrawStatus.SUCCESS == WithdrawStatus.valueOf(dto.getStatus())) {

                if (StringUtils.isBlank(dto.getCertificateUrl())) {
                    jsonResult.remind("转账成功时, 转账凭证URL 不能为空",log);
                    return;
                }
                customerWithdraw.setCertificateUrl(dto.getCertificateUrl());

                // 交易流水
                MallOrder mallOrder = new MallOrder();
                String orderNum = String.format("%s%d%d", String.format("%03d", userInfoDto.mall.getId()), 4L, new Date().getTime()); // 生产订单号 4L代表提现类型
                mallOrder.setMallId(userInfoDto.mall.getId());
                mallOrder.setOrderNum(orderNum);
                CustomerFundFlow customerFundFlow = CustomerFundFlowHelper.SINGLEONE.create(customerFund, mallOrder, customerWithdraw.getAmount(), BigDecimal.ZERO, customerWithdraw.getAmount(), FundTransactionFlow.EXPEND, CustomerFundFlowTransactionType.WITHDRAW, "");
                customerFundFlowRepository.save(customerFundFlow);

                //商家冻结资金减少,总金额减少
                customerFund.setTotalAmount(customerFund.getTotalAmount().subtract(customerWithdraw.getAmount()));
                customerFund.setFrozen(customerFund.getFrozen().subtract(customerWithdraw.getAmount()));
                customerFund = customerFundRepository.save(customerFund);

                //提现审核通过
                customerWithdraw.setStatus(WithdrawStatus.SUCCESS);
                customerWithdraw.setTransactionId(customerFundFlow.getMallOrderNum());
                customerWithdraw.setCertificateUrl(dto.getCertificateUrl());
                customerWithdrawRepository.save(customerWithdraw);

                // 提现成功记录
                withdrawEvent.setStatus(WithdrawStatus.SUCCESS);
                withdrawEventRepository.save(withdrawEvent);
            }
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /mall/customer/withdraw/info 平台 买家提现详情
     * @apiGroup MALL_WITHDRAW_AUDIT
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {long} id 提现ID
     *
     * @apiSuccess {String} certificateUrl 提现帐号信息 (提现成功,显示该字段值)
     * @apiSuccess {String} remark 备注 (提现失败,显示该字段值)
     *
     * @apiSuccessExample { json } Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  "data" : {
     *           "certificateUrl": "843523450987234.jpg",
     *           "remark": "招商+2354283957+二蛋"
     *      }
     *  }
     */
    @RequestMapping(value = Routes.MALL_CUSTOMER_WITHDRAW_INFO, method = RequestMethod.GET)
    public JsonResult customerWithdrawInfo (HttpServletRequest request, MerchantWithdrawDto dto) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getId() == null) {
                jsonResult.remind(MerchantWithdraw.CHECK_ID_IS_NOT_NULL,log);;
                return;
            }
            CustomerWithdraw customerWithdraw = customerWithdrawRepository.findByIdAndMallId(dto.getId(), userInfoDto.mall.getId());
            jsonResult.data = customerWithdraw;
        };
        return doing.go(request, log);
    }
}
